﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Diagnostics;
using System.Net;
using System.Threading;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Xml;
using System.Xml.Linq;
using System.Configuration;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Queue;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Table;
using Microsoft.ServiceBus;
using Microsoft.ServiceBus.Messaging;
using System.Globalization;
using System.Linq;


namespace jobcancel
{
    class jobcancel
    {
       
        private const string TABLE = "jobtable";
        //name of command topic
        private const string CQNAME = "cqueue";
        //name of status topic
        private const string RQNAME = "outqueue";
        //name of service bus
        private const string SBNAME = "<service bus namespace>";
        //service bus key
        private const string SBKEY = "<service bus key>";
        //service bus owner
        private const string SBISSUER = "owner";
        //storage credentials
        private const string _storageacc = "<storage account name>";
        private const string _storagekey = "<storage key>";

        //Connection Strings
        private const string _sbconnectionstring = "Endpoint=sb://<service bus namespace>.servicebus.windows.net;SharedSecretIssuer=owner;SharedSecretValue=<service bus key>";
        private const string _connectionstring = "DefaultEndpointsProtocol=https;AccountName=<storage account name>;AccountKey=<storage key>";


        public class JobEntity : TableEntity
        {
            public JobEntity(string node, string jobid)
            {
                this.PartitionKey = node;
                this.RowKey = jobid;
            }
            public JobEntity() { }
            public string Status { get; set; }
            public DateTime TimeIn { get; set; }
            public DateTime TimeUpdated { get; set; }
        }

        static int Main(string[] args)
        {
            string table = "";
            string jobid = "";

            if (args.Length !=2)
            {
                Console.WriteLine("Usage: jobcancel <job table>  <job id>");
                return 1;
            }
            else
            {
                table = args[0];          
                jobid = args[1];
            }
            
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(_connectionstring);
            CloudQueueClient queueclient = storageAccount.CreateCloudQueueClient();
            
            CloudTableClient tableclient = storageAccount.CreateCloudTableClient();
            CloudTable jobtable = tableclient.GetTableReference(TABLE);

            var sbnamespace = NamespaceManager.CreateFromConnectionString(_sbconnectionstring);
            
            //connect to results topic
            TopicClient rqclient = TopicClient.CreateFromConnectionString(_sbconnectionstring, RQNAME);
            TopicClient cqclient = TopicClient.CreateFromConnectionString(_sbconnectionstring, CQNAME);
            
            TableQuery<JobEntity> newquery = new TableQuery<JobEntity>().Where(TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.Equal, jobid));
            var results = jobtable.ExecuteQuery(newquery);
            foreach (var item in results)
                {
                    Console.WriteLine("{0:-10}\t{1:-16}\t{2:-10}\t{3:G}\t{4:G}", item.PartitionKey, item.RowKey, item.Status, item.TimeIn, item.TimeUpdated);
                }
            JobEntity result = results.LastOrDefault<JobEntity>();
            if (result.Status == "Running")
            {
                BrokeredMessage msg = new BrokeredMessage("CANCEL");
                msg.Properties["JobID"] = jobid;
                cqclient.Send(msg);
                Console.WriteLine("Cancellation request for job id: {0} sent.", jobid);
                return 0;
            }
            else
            {
                result.PartitionKey = Dns.GetHostName();
                result.Status = "Cancelled";
                result.TimeUpdated = DateTime.Now;
                TableOperation update = TableOperation.InsertOrReplace(result);
                BrokeredMessage msg = new BrokeredMessage("CANCELLED");
                msg.Properties["JobID"] = jobid;
                jobtable.Execute(update);
                rqclient.Send(msg);
                Console.WriteLine("Job ID: {0} cancelled.", jobid);
                return 0;

            }
        }
    }
}
